package com.pretty.adminapp.service;

import com.google.common.collect.Sets;
import com.pretty.adminapp.dao.um.*;
import com.pretty.adminapp.pojo.model.um.DataScope;
import com.pretty.adminapp.pojo.model.um.Employee;
import com.pretty.adminapp.pojo.model.um.EmployeeRole;
import com.pretty.adminapp.pojo.model.um.RolePermission;
import com.pretty.adminapp.pojo.po.AdminUserDetail;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author 自定义验证
 */
@Service
public class SecurityAuthenticationProvider implements AuthenticationProvider, UserDetailsService {
    @Autowired
    private EmployeeDao userDao;
    @Autowired
    private ModuleDao moduleDao;
    @Autowired
    private DataScopeDao dataScopeDao;
    @Autowired
    private EmployeeRoleDao userRoleDao;
    @Autowired
    private RolePermissionDao rolePermissionDao;

    @Override
    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
        String username = authentication.getName();
        String password = (String) authentication.getCredentials();

        System.err.println("用户名：" + username);
        System.err.println("密码：" + password);

        Employee user = this.findByAccount(username);
        if (user == null) {
            throw new BadCredentialsException("Username not found.");
        }
        //加密过程在这里体现
        if (!user.verifyPassword(password)) {
            throw new BadCredentialsException("Wrong password.");
        }
        AdminUserDetail adminUserDetail = (AdminUserDetail) this.loadUserByUsername(username);
        Collection<? extends GrantedAuthority> authorities = adminUserDetail.getAuthorities();
        return new UsernamePasswordAuthenticationToken(adminUserDetail, password, authorities);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
    }


    @Override
    public UserDetails loadUserByUsername(String account) throws UsernameNotFoundException {
        Employee user = this.findByAccount(account);
        if (user == null) {
            throw new UsernameNotFoundException(account + " not found");
        }
        Set<GrantedAuthority> authorities = new HashSet<>();

        Set<String> permissions = findPermissions(account);
        if (CollectionUtils.isNotEmpty(permissions)) {
            permissions.forEach(it -> {
                authorities.add(new SimpleGrantedAuthority(it));
            });
        }
        DataScope dataScope = new DataScope();
        dataScope.setEmployeeId(user.getId());
        dataScope.setActive(true);
        Example<DataScope> example = Example.of(dataScope);
        List<DataScope> dataScopes = dataScopeDao.findAll(example);
        Map<Integer,Long> scopes = new HashMap<>();
        if(CollectionUtils.isNotEmpty(dataScopes)){
            dataScopes.forEach(it->{
                scopes.put(it.getType(),it.getValue());
            });
        }
        String password = user.getPassword();
        AdminUserDetail adminUserDetail = new AdminUserDetail();
        adminUserDetail.setUsername(account);
        adminUserDetail.setPassword(password + user.getSalt());
        adminUserDetail.setGrantedAuthorities(authorities);
        adminUserDetail.setScope(scopes);
        return adminUserDetail;
    }

    /**
     * 根据账号Account查询当前用户
     *
     * @param account
     * @return
     */
    public Employee findByAccount(String account) {
        Employee user = new Employee();
        user.setLoginName(account);
        user.setActive(true);
        Example example = Example.of(user);
        return userDao.findOne(example);
    }

    /**
     * 获取资源集合
     *
     * @param account
     * @return
     */
    public Set<String> findPermissions(String account) {
        Set<String> set = Sets.newHashSet();
        Employee user = findByAccount(account);
        EmployeeRole query = new EmployeeRole();
        query.setActive(true);
        query.setEmployeeId(user.getId());
        Example example = Example.of(query);
        List<EmployeeRole> userRoles = userRoleDao.findAll(example);
        for (EmployeeRole userRole : userRoles) {
            RolePermission roleModuleQ = new RolePermission();
            roleModuleQ.setRoleId(userRole.getRoleId());
            roleModuleQ.setActive(true);
            example = Example.of(roleModuleQ);
            List<RolePermission> rolePermissions = rolePermissionDao.findAll(example);
            for (RolePermission rolePermission : rolePermissions) {
                set.add(rolePermission.getPermission().getCode());
            }
        }

        return set;
    }
}
